<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/blog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/blog/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.2/css/all.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css">

<script class="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"littlefxc.github.io","root":"/blog/","images":"/blog/images","scheme":"Mist","version":"8.2.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/blog/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}};
  </script>
<meta name="description" content="[TOC]  转载于https:&#x2F;&#x2F;www.cnblogs.com&#x2F;crazymakercircle&#x2F;p&#x2F;11704077.html  1 概述1.1 SpringCloud Gateway 简介SpringCloud Gateway 是 Spring Cloud 的一个全新项目，该项目是基于 Spring 5.0，Spring Boot 2.0 和 Project Reactor 等技术开发的网">
<meta property="og:type" content="article">
<meta property="og:title" content="SpringCloudGateway">
<meta property="og:url" content="http://littlefxc.github.io/2021/04/07/SpringCloudGateway/index.html">
<meta property="og:site_name" content="一年春又来">
<meta property="og:description" content="[TOC]  转载于https:&#x2F;&#x2F;www.cnblogs.com&#x2F;crazymakercircle&#x2F;p&#x2F;11704077.html  1 概述1.1 SpringCloud Gateway 简介SpringCloud Gateway 是 Spring Cloud 的一个全新项目，该项目是基于 Spring 5.0，Spring Boot 2.0 和 Project Reactor 等技术开发的网">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/strip-20210407151947510.gif">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947526.jpeg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947542.jpeg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947561.jpeg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NzIyNDc1,size_16,color_FFFFFF,t_70-20210407151947718.png">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/strip-20210407151947740.gif">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947763.jpeg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947778.jpeg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0ZvdXNlXw==,size_16,color_FFFFFF,t_70-20210407151947799.png">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NyYXp5bWFrZXJjaXJjbGU=,size_16,color_FFFFFF,t_70-20210407151947874.png">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/spring-cloud-gateway-fliter-order-20210407151948451.png">
<meta property="article:published_time" content="2021-04-07T06:42:04.000Z">
<meta property="article:modified_time" content="2021-04-07T08:10:29.157Z">
<meta property="article:author" content="一年春又来">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/littlefxc/oss/raw/master/images/strip-20210407151947510.gif">


<link rel="canonical" href="http://littlefxc.github.io/2021/04/07/SpringCloudGateway/">


<script class="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>
<title>SpringCloudGateway | 一年春又来</title>
  




  <noscript>
  <style>
  body { margin-top: 2rem; }

  .use-motion .menu-item,
  .use-motion .sidebar,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header {
    visibility: visible;
  }

  .use-motion .header,
  .use-motion .site-brand-container .toggle,
  .use-motion .footer { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle,
  .use-motion .custom-logo-image {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line {
    transform: scaleX(1);
  }

  .search-pop-overlay, .sidebar-nav { display: none; }
  .sidebar-panel { display: block; }
  </style>
</noscript>

<link rel="alternate" href="/blog/atom.xml" title="一年春又来" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/blog/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">一年春又来</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/blog/" rel="section"><i class="home                          //首页 fa-fw"></i>首页</a></li>
        <li class="menu-item menu-item-archives"><a href="/blog/archives/" rel="section"><i class="archive          //归档 fa-fw"></i>归档</a></li>
        <li class="menu-item menu-item-categories"><a href="/blog/categories/" rel="section"><i class="th           //分类 fa-fw"></i>分类</a></li>
        <li class="menu-item menu-item-tags"><a href="/blog/tags/" rel="section"><i class="tags                     //标签 fa-fw"></i>标签</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#1-%E6%A6%82%E8%BF%B0"><span class="nav-text">1 概述</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-1-SpringCloud-Gateway-%E7%AE%80%E4%BB%8B"><span class="nav-text">1.1 SpringCloud Gateway 简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-2-SpringCloud-Gateway-%E7%89%B9%E5%BE%81"><span class="nav-text">1.2 SpringCloud Gateway 特征</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-3-SpringCloud-Gateway%E5%92%8C%E6%9E%B6%E6%9E%84"><span class="nav-text">1.3 SpringCloud Gateway和架构</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-3-1-SpringCloud-Zuul%E7%9A%84IO%E6%A8%A1%E5%9E%8B"><span class="nav-text">1.3.1 SpringCloud Zuul的IO模型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-3-2-Webflux-%E6%9C%8D%E5%8A%A1%E5%99%A8"><span class="nav-text">1.3.2 Webflux 服务器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-3-3-Spring-Cloud-Gateway%E7%9A%84%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B"><span class="nav-text">1.3.3 Spring Cloud Gateway的处理流程</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#2-%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F"><span class="nav-text">2 路由配置方式</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#2-1-%E5%9F%BA%E7%A1%80URI%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F"><span class="nav-text">2.1 基础URI路由配置方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-2-%E5%9F%BA%E4%BA%8E%E4%BB%A3%E7%A0%81%E7%9A%84%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F"><span class="nav-text">2.2 基于代码的路由配置方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-3-%E5%92%8C%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E7%9B%B8%E7%BB%93%E5%90%88%E7%9A%84%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F"><span class="nav-text">2.3 和注册中心相结合的路由配置方式</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#3-%E8%B7%AF%E7%94%B1%E5%8C%B9%E9%85%8D%E8%A7%84%E5%88%99"><span class="nav-text">3 路由匹配规则</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#3-1-Predicate-%E6%96%AD%E8%A8%80%E6%9D%A1%E4%BB%B6-%E8%BD%AC%E5%8F%91%E8%A7%84%E5%88%99-%E4%BB%8B%E7%BB%8D"><span class="nav-text">3.1 Predicate 断言条件(转发规则)介绍</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-2-%E9%80%9A%E8%BF%87%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E5%8C%B9%E9%85%8D"><span class="nav-text">1.5.2 通过请求参数匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-3-%E9%80%9A%E8%BF%87-Header-%E5%B1%9E%E6%80%A7%E5%8C%B9%E9%85%8D"><span class="nav-text">1.5.3 通过 Header 属性匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-4-%E9%80%9A%E8%BF%87-Cookie-%E5%8C%B9%E9%85%8D"><span class="nav-text">1.5.4 通过 Cookie 匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-5-%E9%80%9A%E8%BF%87-Host-%E5%8C%B9%E9%85%8D"><span class="nav-text">1.5.5 通过 Host 匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-6-%E9%80%9A%E8%BF%87%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F%E5%8C%B9%E9%85%8D"><span class="nav-text">1.5.6 通过请求方式匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-7-%E9%80%9A%E8%BF%87%E8%AF%B7%E6%B1%82%E8%B7%AF%E5%BE%84%E5%8C%B9%E9%85%8D"><span class="nav-text">1.5.7 通过请求路径匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-8-%E9%80%9A%E8%BF%87%E8%AF%B7%E6%B1%82-ip-%E5%9C%B0%E5%9D%80%E8%BF%9B%E8%A1%8C%E5%8C%B9%E9%85%8D"><span class="nav-text">1.5.8 通过请求 ip 地址进行匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-10-%E7%BB%84%E5%90%88%E4%BD%BF%E7%94%A8"><span class="nav-text">1.5.10 组合使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-2-%E8%BF%87%E6%BB%A4%E5%99%A8%E8%A7%84%E5%88%99%EF%BC%88Filter%EF%BC%89"><span class="nav-text">3.2 过滤器规则（Filter）</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%87%E6%BB%A4%E5%99%A8%E8%A7%84%E5%88%99%EF%BC%88Filter%EF%BC%89"><span class="nav-text">过滤器规则（Filter）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#PrefixPath"><span class="nav-text">PrefixPath</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#RedirectTo"><span class="nav-text">RedirectTo</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#RemoveRequestHeader"><span class="nav-text">RemoveRequestHeader</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#RemoveResponseHeader"><span class="nav-text">RemoveResponseHeader</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#RemoveRequestParameter"><span class="nav-text">RemoveRequestParameter</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#RewritePath"><span class="nav-text">RewritePath</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#SetPath"><span class="nav-text">SetPath</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#SetRequestHeader"><span class="nav-text">SetRequestHeader</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#SetStatus"><span class="nav-text">SetStatus</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#StripPrefix"><span class="nav-text">StripPrefix</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#RequestSize"><span class="nav-text">RequestSize</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Default-filters"><span class="nav-text">Default-filters</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-3-%E9%80%9A%E8%BF%87%E4%BB%A3%E7%A0%81%E8%BF%9B%E8%A1%8C%E9%85%8D%E7%BD%AE"><span class="nav-text">3.3 通过代码进行配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-2-%E5%AE%9E%E7%8E%B0%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7"><span class="nav-text">3.2 实现熔断降级</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#4-%E9%AB%98%E7%BA%A7%E9%85%8D%E7%BD%AE"><span class="nav-text">4 高级配置</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#4-1-%E5%88%86%E5%B8%83%E5%BC%8F%E9%99%90%E6%B5%81"><span class="nav-text">4.1 分布式限流</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-2-%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%E9%85%8D%E7%BD%AE"><span class="nav-text">4.2 健康检查配置</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#maven%E4%BE%9D%E8%B5%96"><span class="nav-text">maven依赖</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="nav-text">配置文件</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-3-%E7%BB%9F%E4%B8%80%E9%85%8D%E7%BD%AE%E8%B7%A8%E5%9F%9F%E8%AF%B7%E6%B1%82%EF%BC%9A"><span class="nav-text">4.3 统一配置跨域请求：</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#5-%E6%95%B4%E5%90%88Nacos"><span class="nav-text">5 整合Nacos</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#maven%E4%BE%9D%E8%B5%96-1"><span class="nav-text">maven依赖</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E9%85%8D%E7%BD%AE%EF%BC%9A%E4%BB%8ENacos%E8%8E%B7%E5%8F%96%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85%E6%B8%85%E5%8D%95"><span class="nav-text">服务发现配置：从Nacos获取微服务提供者清单</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#nacos%E5%AE%9E%E7%8E%B0%E5%8A%A8%E6%80%81%E9%85%8D%E7%BD%AE"><span class="nav-text">nacos实现动态配置</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#6-%E6%95%B4%E5%90%88Swagger%E8%81%9A%E5%90%88%E5%BE%AE%E6%9C%8D%E5%8A%A1%E7%B3%BB%E7%BB%9FAPI%E6%96%87%E6%A1%A3"><span class="nav-text">6 整合Swagger聚合微服务系统API文档</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#maven%E4%BE%9D%E8%B5%96-2"><span class="nav-text">maven依赖</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6-1"><span class="nav-text">配置文件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%88%E6%9E%9C%EF%BC%9A"><span class="nav-text">效果：</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#7-Gatway-%E7%BD%91%E5%85%B3%E7%9A%84%E8%BF%87%E6%BB%A4%E5%99%A8%E5%BC%80%E5%8F%91"><span class="nav-text">7 Gatway 网关的过滤器开发</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#7-1-%E8%BF%87%E6%BB%A4%E5%99%A8%E7%9A%84%E6%89%A7%E8%A1%8C%E6%AC%A1%E5%BA%8F"><span class="nav-text">7.1 过滤器的执行次序</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-2%E5%AE%9A%E4%B9%89%E5%85%A8%E5%B1%80%E8%BF%87%E6%BB%A4%E5%99%A8"><span class="nav-text">7.2定义全局过滤器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-3%E5%AE%9A%E4%B9%89%E5%B1%80%E9%83%A8%E8%BF%87%E6%BB%A4%E5%99%A8"><span class="nav-text">7.3定义局部过滤器</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#8-%E6%95%B4%E5%90%88Sentinel%E5%AE%8C%E6%88%90%E6%B5%81%E6%8E%A7%E5%92%8C%E9%99%8D%E7%BA%A7"><span class="nav-text">8 整合Sentinel完成流控和降级</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#maven%E4%BE%9D%E8%B5%96-3"><span class="nav-text">maven依赖</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6-2"><span class="nav-text">配置文件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%99%90%E6%B5%81%E8%A7%84%E5%88%99%E9%80%9A%E7%94%A8%E9%85%8D%E7%BD%AE"><span class="nav-text">限流规则通用配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%99%90%E6%B5%81%E8%A7%84%E5%88%99%E8%AE%BE%E7%BD%AE"><span class="nav-text">限流规则设置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81%E5%8F%82%E6%95%B0"><span class="nav-text">网关限流参数</span></a></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">一年春又来</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/blog/archives/">
        
          <span class="site-state-item-count">184</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/blog/categories/">
          
        <span class="site-state-item-count">35</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/blog/tags/">
          
        <span class="site-state-item-count">115</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://littlefxc.github.io/2021/04/07/SpringCloudGateway/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/blog/images/avatar.gif">
      <meta itemprop="name" content="一年春又来">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="一年春又来">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          SpringCloudGateway
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      

      <time title="创建时间：2021-04-07 14:42:04 / 修改时间：16:10:29" itemprop="dateCreated datePublished" datetime="2021-04-07T14:42:04+08:00">2021-04-07</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <p>[TOC]</p>
<blockquote>
<p>转载于<a target="_blank" rel="noopener" href="https://www.cnblogs.com/crazymakercircle/p/11704077.html">https://www.cnblogs.com/crazymakercircle/p/11704077.html</a></p>
</blockquote>
<h1 id="1-概述"><a href="#1-概述" class="headerlink" title="1 概述"></a>1 概述</h1><h2 id="1-1-SpringCloud-Gateway-简介"><a href="#1-1-SpringCloud-Gateway-简介" class="headerlink" title="1.1 SpringCloud Gateway 简介"></a><strong>1.1</strong> SpringCloud Gateway 简介</h2><p>SpringCloud Gateway 是 Spring Cloud 的一个全新项目，该项目是基于 Spring 5.0，Spring Boot 2.0 和 Project Reactor 等技术开发的网关，它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。</p>
<p>SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关，目标是替代 Zuul，在Spring Cloud 2.0以上版本中，没有对新版本的Zuul 2.0以上最新高性能版本进行集成，仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能，SpringCloud Gateway是基于WebFlux框架实现的，而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。</p>
<p>Spring Cloud Gateway 的目标，不仅提供统一的路由方式，并且基于 Filter 链的方式提供了网关基本的功能，例如：安全，监控/指标，和限流。</p>
<p>提前声明：<strong>Spring Cloud Gateway 底层使用了高性能的通信框架Netty</strong>。</p>
<h2 id="1-2-SpringCloud-Gateway-特征"><a href="#1-2-SpringCloud-Gateway-特征" class="headerlink" title="1.2 SpringCloud Gateway 特征"></a><strong>1.2</strong> SpringCloud Gateway 特征</h2><p>SpringCloud官方，对SpringCloud Gateway 特征介绍如下：</p>
<p>（1）基于 Spring Framework 5，Project Reactor 和 Spring Boot 2.0</p>
<p>（2）集成 Hystrix 断路器</p>
<p>（3）集成 Spring Cloud DiscoveryClient</p>
<p>（4）Predicates 和 Filters 作用于特定路由，易于编写的 Predicates 和 Filters</p>
<p>（5）具备一些网关的高级功能：动态路由、限流、路径重写</p>
<p>从以上的特征来说，和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别，还是在底层的通信框架上。</p>
<p>简单说明一下上文中的三个术语：</p>
<p><strong>（</strong>1<strong>）</strong>Filter<strong>（过滤器）</strong>：</p>
<p>和Zuul的过滤器在概念上类似，可以使用它拦截和修改请求，并且对上游的响应，进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。</p>
<p>（2）<strong>Route</strong>（路由）：</p>
<p>网关配置的基本组成模块，和Zuul的路由配置模块类似。一个<strong>Route模块</strong>由一个 ID，一个目标 URI，一组断言和一组过滤器定义。如果断言为真，则路由匹配，目标URI会被访问。</p>
<p><strong>（</strong>3<strong>）</strong>Predicate<strong>（断言）</strong>：</p>
<p>这是一个 Java 8 的 Predicate，可以使用它来匹配来自 HTTP 请求的任何内容，例如 headers 或参数。<strong>断言的</strong>输入类型是一个 ServerWebExchange。</p>
<h2 id="1-3-SpringCloud-Gateway和架构"><a href="#1-3-SpringCloud-Gateway和架构" class="headerlink" title="1.3 SpringCloud Gateway和架构"></a><strong>1.3</strong> SpringCloud Gateway和架构</h2><p>Spring在2017年下半年迎来了Webflux，Webflux的出现填补了Spring在响应式编程上的空白，Webflux的响应式编程不仅仅是编程风格的改变，而且对于一系列的著名框架，都提供了响应式访问的开发包，比如Netty、Redis等等。</p>
<p>SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件，底层使用了Netty通讯框架。<br><a target="_blank" rel="noopener" href="https://upload-images.jianshu.io/upload_images/19816137-8758f092be21e6f7.gif?imageMogr2/auto-orient/strip"><img src="https://gitee.com/littlefxc/oss/raw/master/images/strip-20210407151947510.gif" alt="在这里插入图片描述"></a></p>
<h2 id="1-3-1-SpringCloud-Zuul的IO模型"><a href="#1-3-1-SpringCloud-Zuul的IO模型" class="headerlink" title="1.3.1 SpringCloud Zuul的IO模型"></a><strong>1.3.1</strong> SpringCloud Zuul的IO模型</h2><p>Springcloud中所集成的Zuul版本，采用的是Tomcat容器，使用的是传统的Servlet IO处理模型。</p>
<p>大家知道，servlet由servlet container进行生命周期管理。container启动时构造servlet对象并调用servlet init()进行初始化；container关闭时调用servlet destory()销毁servlet；container运行时接受请求，并为每个请求分配一个线程（一般从线程池中获取空闲线程）然后调用service()。</p>
<p>弊端：servlet是一个简单的网络IO模型，当请求进入servlet container时，servlet container就会为其绑定一个线程，在并发不高的场景下这种模型是适用的，但是一旦并发上升，线程数量就会上涨，而线程资源代价是昂贵的（上线文切换，内存消耗大）严重影响请求的处理时间。在一些简单的业务场景下，不希望为每个request分配一个线程，只需要1个或几个线程就能应对极大并发的请求，这种业务场景下servlet模型没有优势。<br><a target="_blank" rel="noopener" href="https://upload-images.jianshu.io/upload_images/19816137-bb466f6b0135bb71?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><img src="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947526.jpeg" alt="在这里插入图片描述"></a></p>
<p>所以Springcloud Zuul 是基于servlet之上的一个阻塞式处理模型，即spring实现了处理所有request请求的一个servlet（DispatcherServlet），并由该servlet阻塞式处理处理。所以Springcloud Zuul无法摆脱servlet模型的弊端。虽然Zuul 2.0开始，使用了Netty，并且已经有了大规模Zuul 2.0集群部署的成熟案例，但是，Springcloud官方已经没有集成改版本的计划了。</p>
<h2 id="1-3-2-Webflux-服务器"><a href="#1-3-2-Webflux-服务器" class="headerlink" title="1.3.2 Webflux 服务器"></a><strong>1.3.2</strong> Webflux 服务器</h2><p>Webflux模式替换了旧的Servlet线程模型。用少量的线程处理request和response io操作，这些线程称为Loop线程，而业务交给响应式编程框架处理，响应式编程是非常灵活的，用户可以将业务中阻塞的操作提交到响应式框架的work线程中执行，而不阻塞的操作依然可以在Loop线程中进行处理，大大提高了Loop线程的利用率。官方结构图：</p>
<p><a target="_blank" rel="noopener" href="https://upload-images.jianshu.io/upload_images/19816137-dad0e43fc31f4536?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><img src="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947542.jpeg" alt="在这里插入图片描述"></a></p>
<p>Webflux虽然可以兼容多个底层的通信框架，但是一般情况下，底层使用的还是Netty，毕竟，Netty是目前业界认可的最高性能的通信框架。而Webflux的Loop线程，正好就是著名的Reactor 模式IO处理模型的Reactor线程，如果使用的是高性能的通信框架Netty，这就是Netty的EventLoop线程。</p>
<p>关于Reactor线程模型，和Netty通信框架的知识，是Java程序员的重要、必备的内功，个中的原理，具体请参见尼恩编著的《Netty、Zookeeper、Redis高并发实战》一书，这里不做过多的赘述。</p>
<h2 id="1-3-3-Spring-Cloud-Gateway的处理流程"><a href="#1-3-3-Spring-Cloud-Gateway的处理流程" class="headerlink" title="1.3.3 Spring Cloud Gateway的处理流程"></a><strong>1.3.3</strong> Spring Cloud Gateway的处理流程</h2><p>客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由，将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑，然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前（“pre”）或之后（“post”）执行业务逻辑。<br><a target="_blank" rel="noopener" href="https://upload-images.jianshu.io/upload_images/19816137-eeedbd49be096c05?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><img src="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947561.jpeg" alt="在这里插入图片描述"></a></p>
<h1 id="2-路由配置方式"><a href="#2-路由配置方式" class="headerlink" title="2 路由配置方式"></a>2 路由配置方式</h1><h2 id="2-1-基础URI路由配置方式"><a href="#2-1-基础URI路由配置方式" class="headerlink" title="2.1 基础URI路由配置方式"></a>2.1 基础URI路由配置方式</h2><p>如果请求的目标地址，是单个的URI资源路径，配置文件示例如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">        <span class="string">-id:</span> <span class="string">url-proxy-1</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://blog.csdn.net</span></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line">            <span class="string">-Path=/csdn</span></span><br></pre></td></tr></table></figure>

<p>各字段含义如下：</p>
<ul>
<li><p>id：我们自定义的路由 ID，保持唯一</p>
</li>
<li><p>uri：目标服务地址</p>
</li>
<li><p>predicates：路由条件，Predicate 接受一个输入参数，返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑（比如：与，或，非）。</p>
</li>
</ul>
<p>上面这段配置的意思是，配置了一个 id 为 url-proxy-1的URI代理规则，路由的规则为：</p>
<p>当访问地址<a target="_blank" rel="noopener" href="http://localhost:8080/csdn/1.jsp%E6%97%B6%EF%BC%8C">http://localhost:8080/csdn/1.jsp时，</a></p>
<p>会路由到上游地址<a target="_blank" rel="noopener" href="https://blog.csdn.net/1.jsp%E3%80%82">https://blog.csdn.net/1.jsp。</a></p>
<h2 id="2-2-基于代码的路由配置方式"><a href="#2-2-基于代码的路由配置方式" class="headerlink" title="2.2 基于代码的路由配置方式"></a>2.2 基于代码的路由配置方式</h2><p>转发功能同样可以通过代码来实现，我们可以在启动类 GateWayApplication 中添加方法 customRouteLocator() 来定制转发规则。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.springcloud.gateway;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.route.RouteLocator;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"> </span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">GatewayApplication</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SpringApplication.run(GatewayApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> RouteLocator <span class="title">customRouteLocator</span><span class="params">(RouteLocatorBuilder builder)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> builder.routes()</span><br><span class="line">                .route(<span class="string">&quot;path_route&quot;</span>, r -&gt; r.path(<span class="string">&quot;/csdn&quot;</span>)</span><br><span class="line">                        .uri(<span class="string">&quot;https://blog.csdn.net&quot;</span>))</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>我们在yaml配置文件中注销掉相关路由的配置，重启服务，访问链接：<a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080/</a> csdn， 可以看到和上面一样的页面，证明我们测试成功。</p>
<p>上面两个示例中 uri 都是指向了我的CSDN博客，在实际项目使用中可以将 uri 指向对外提供服务的项目地址，统一对外输出接口。</p>
<h2 id="2-3-和注册中心相结合的路由配置方式"><a href="#2-3-和注册中心相结合的路由配置方式" class="headerlink" title="2.3 和注册中心相结合的路由配置方式"></a>2.3 和注册中心相结合的路由配置方式</h2><p>在uri的schema协议部分为自定义的lb:类型，表示从微服务注册中心（如Eureka）订阅服务，并且进行服务的路由。</p>
<p>一个典型的示例如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8084</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="string">-id:</span> <span class="string">seckill-provider-route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">lb://seckill-provider</span></span><br><span class="line">        <span class="attr">predicates:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Path=/seckill-provider/**</span></span><br><span class="line"></span><br><span class="line">      <span class="string">-id:</span> <span class="string">message-provider-route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">lb://message-provider</span></span><br><span class="line">        <span class="attr">predicates:</span></span><br><span class="line">        <span class="string">-Path=/message-provider/**</span></span><br><span class="line"></span><br><span class="line"><span class="attr">application:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">cloud-gateway</span></span><br><span class="line"></span><br><span class="line"><span class="attr">eureka:</span></span><br><span class="line">  <span class="attr">instance:</span></span><br><span class="line">    <span class="attr">prefer-ip-address:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">client:</span></span><br><span class="line">    <span class="attr">service-url:</span></span><br><span class="line">      <span class="attr">defaultZone:</span> <span class="string">http://localhost:8888/eureka/</span></span><br></pre></td></tr></table></figure>

<p>注册中心相结合的路由配置方式，与单个URI的路由配置，区别其实很小，仅仅在于URI的schema协议不同。单个URI的地址的schema协议，一般为http或者https协议。</p>
<h1 id="3-路由匹配规则"><a href="#3-路由匹配规则" class="headerlink" title="3 路由匹配规则"></a>3 路由匹配规则</h1><p>Spring Cloud Gateway 的功能很强大，我们仅仅通过 Predicates 的设计就可以看出来，前面我们只是使用了 predicates 进行了简单的条件匹配，其实 Spring Cloud Gataway 帮我们内置了很多 Predicates 功能。</p>
<p>Spring Cloud Gateway 是通过 Spring WebFlux 的 HandlerMapping 做为底层支持来匹配到转发路由，Spring Cloud Gateway 内置了很多 Predicates 工厂，这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配，多个 Predicates 工厂可以组合使用。</p>
<p><a target="_blank" rel="noopener" href="https://img-blog.csdnimg.cn/20200527213652534.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NzIyNDc1,size_16,color_FFFFFF,t_70"><img src="https://gitee.com/littlefxc/oss/raw/master/images/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NzIyNDc1,size_16,color_FFFFFF,t_70-20210407151947718.png" alt="在这里插入图片描述"></a></p>
<p>gateWay的主要功能之一是转发请求，转发规则的定义主要包含三个部分</p>
<table>
<thead>
<tr>
<th align="left">名称</th>
<th align="left">描述</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Route（路由）</td>
<td align="left">路由是网关的基本单元，由ID、URI、一组Predicate、一组Filter组成，根据Predicate进行匹配转发。</td>
</tr>
<tr>
<td align="left">Predicate（谓语、断言）</td>
<td align="left">路由转发的判断条件，目前SpringCloud Gateway支持多种方式，常见如：Path、Query、Method、Header等，写法必须遵循 key=vlue的形式</td>
</tr>
<tr>
<td align="left">Filter（过滤器）</td>
<td align="left">过滤器是路由转发请求时所经过的过滤逻辑，可用于修改请求、响应内容</td>
</tr>
</tbody></table>
<blockquote>
<p>其中Route和Predicate必须同时申明</p>
</blockquote>
<p>例子：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">//通过配置文件配置</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">gate_route</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">http://localhost:9023</span></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line">          <span class="comment">## 当请求的路径为gate、rule开头的时，转发到http://localhost:9023服务器上</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Path=/gate/**,/rule/**</span></span><br><span class="line">        <span class="comment">### 请求路径前加上/app</span></span><br><span class="line">          <span class="attr">filters:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="string">PrefixPath=/app</span></span><br></pre></td></tr></table></figure>

<h2 id="3-1-Predicate-断言条件-转发规则-介绍"><a href="#3-1-Predicate-断言条件-转发规则-介绍" class="headerlink" title="3.1 Predicate 断言条件(转发规则)介绍"></a>3.1 Predicate 断言条件(转发规则)介绍</h2><p>Predicate 来源于 Java 8，是 Java 8 中引入的一个函数，Predicate 接受一个输入参数，返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑（比如：与，或，非）。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。</p>
<p>在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则，有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。<br><a target="_blank" rel="noopener" href="https://upload-images.jianshu.io/upload_images/19816137-bb046dbf19bee1b4.gif?imageMogr2/auto-orient/strip"><img src="https://gitee.com/littlefxc/oss/raw/master/images/strip-20210407151947740.gif" alt="在这里插入图片描述"></a><br>[<br>说白了 Predicate 就是为了实现一组匹配规则，方便让请求过来找到对应的 Route 进行处理，接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用。</p>
<ul>
<li>转发规则（predicates），假设 转发uri都设定为***<a target="_blank" rel="noopener" href="http://localhost:9023/">http://localhost:9023</a>***</li>
</ul>
<table>
<thead>
<tr>
<th align="left">规则</th>
<th align="left">实例</th>
<th align="left">说明</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Path</td>
<td align="left">- Path=/gate/<strong>,/rule/</strong></td>
<td align="left">## 当请求的路径为gate、rule开头的时，转发到<a href="http://localhost:9023服务器上">http://localhost:9023服务器上</a></td>
</tr>
<tr>
<td align="left">Before</td>
<td align="left">- Before=2017-01-20T17:42:47.789-07:00[America/Denver]</td>
<td align="left">在某个时间之前的请求才会被转发到 <a href="http://localhost:9023服务器上">http://localhost:9023服务器上</a></td>
</tr>
<tr>
<td align="left">After</td>
<td align="left">- After=2017-01-20T17:42:47.789-07:00[America/Denver]</td>
<td align="left">在某个时间之后的请求才会被转发</td>
</tr>
<tr>
<td align="left">Between</td>
<td align="left">- Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver]</td>
<td align="left">在某个时间段之间的才会被转发</td>
</tr>
<tr>
<td align="left">Cookie</td>
<td align="left">- Cookie=chocolate, ch.p</td>
<td align="left">名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发</td>
</tr>
<tr>
<td align="left">Header</td>
<td align="left">- Header=X-Request-Id, \d+</td>
<td align="left">携带参数X-Request-Id或者满足\d+的请求头才会匹配</td>
</tr>
<tr>
<td align="left">Host</td>
<td align="left">- Host=<a target="_blank" rel="noopener" href="http://www.hd123.com/">www.hd123.com</a></td>
<td align="left">当主机名为<a target="_blank" rel="noopener" href="http://www.hd123.com的时候直接转发到http//localhost:9023%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A">www.hd123.com的时候直接转发到http://localhost:9023服务器上</a></td>
</tr>
<tr>
<td align="left">Method</td>
<td align="left">- Method=GET</td>
<td align="left">只有GET方法才会匹配转发请求，还可以限定POST、PUT等请求方式</td>
</tr>
</tbody></table>
<h3 id="1-5-2-通过请求参数匹配"><a href="#1-5-2-通过请求参数匹配" class="headerlink" title="1.5.2 通过请求参数匹配"></a><strong>1.5.2</strong> 通过请求参数匹配</h3><p>Query Route Predicate 支持传入两个参数，一个是属性名一个为属性值，属性值可以是正则表达式。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">  	 <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">        <span class="string">-id:</span> <span class="string">gateway-service</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line">            <span class="string">-Query=smile</span></span><br></pre></td></tr></table></figure>

<p>这样配置，只要请求中包含 smile 属性的参数即可匹配路由。</p>
<p>使用 curl 测试，命令行输入:</p>
<p>curl localhost:8080?smile=x&amp;id=2</p>
<p>经过测试发现只要请求汇总带有 smile 参数即会匹配路由，不带 smile 参数则不会匹配。</p>
<p>还可以将 Query 的值以键值对的方式进行配置，这样在请求过来时会对属性值和正则进行匹配，匹配上才会走路由。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line"></span><br><span class="line">        <span class="string">-id:</span> <span class="string">gateway-service</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line"></span><br><span class="line">            <span class="string">-Query=keep,</span> <span class="string">pu.</span></span><br></pre></td></tr></table></figure>

<p>这样只要当请求中包含 keep 属性并且参数值是以 pu 开头的长度为三位的字符串才会进行匹配和路由。</p>
<p>使用 curl 测试，命令行输入:</p>
<p>curl localhost:8080?keep=pub</p>
<p>测试可以返回页面代码，将 keep 的属性值改为 pubx 再次访问就会报 404,证明路由需要匹配正则表达式才会进行路由。</p>
<h3 id="1-5-3-通过-Header-属性匹配"><a href="#1-5-3-通过-Header-属性匹配" class="headerlink" title="1.5.3 通过 Header 属性匹配"></a><strong>1.5.3</strong> 通过 Header 属性匹配</h3><p>Header Route Predicate 和 Cookie Route Predicate 一样，也是接收 2 个参数，一个 header 中属性名称和一个正则表达式，这个属性值和正则表达式匹配则执行。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line"></span><br><span class="line">        <span class="string">-id:</span> <span class="string">gateway-service</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line"></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Header=X-Request-Id,</span> <span class="string">\d+</span></span><br></pre></td></tr></table></figure>

<p>使用 curl 测试，命令行输入:</p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080</a> -H “X-Request-Id:88”</p>
<p>则返回页面代码证明匹配成功。将参数-H “X-Request-Id:88”改为-H “X-Request-Id:spring”再次执行时返回404证明没有匹配。</p>
<h3 id="1-5-4-通过-Cookie-匹配"><a href="#1-5-4-通过-Cookie-匹配" class="headerlink" title="1.5.4 通过 Cookie 匹配"></a><strong>1.5.4</strong> 通过 Cookie 匹配</h3><p>Cookie Route Predicate 可以接收两个参数，一个是 Cookie name ,一个是正则表达式，路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配，如果匹配上就会执行路由，如果没有匹配上则不执行。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">        <span class="string">-id:</span> <span class="string">gateway-service</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Cookie=sessionId,</span> <span class="string">test</span></span><br></pre></td></tr></table></figure>

<p>使用 curl 测试，命令行输入:</p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080</a> –cookie “sessionId=test”</p>
<p>则会返回页面代码，如果去掉–cookie “sessionId=test”，后台汇报 404 错误。</p>
<h3 id="1-5-5-通过-Host-匹配"><a href="#1-5-5-通过-Host-匹配" class="headerlink" title="1.5.5 通过 Host 匹配"></a><strong>1.5.5</strong> 通过 Host 匹配</h3><p>Host Route Predicate 接收一组参数，一组匹配的域名列表，这个模板是一个 ant 分隔的模板，用.号作为分隔符。它通过参数中的主机地址作为匹配规则。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line"></span><br><span class="line">        <span class="string">-id:</span> <span class="string">gateway-service</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line"></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Host=**.baidu.com</span></span><br></pre></td></tr></table></figure>

<p>使用 curl 测试，命令行输入:</p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080</a> -H “Host: <a target="_blank" rel="noopener" href="http://www.baidu.com&quot;/">www.baidu.com&quot;</a></p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080</a> -H “Host: md.baidu.com”</p>
<p>经测试以上两种 host 均可匹配到 host_route 路由，去掉 host 参数则会报 404 错误。</p>
<h3 id="1-5-6-通过请求方式匹配"><a href="#1-5-6-通过请求方式匹配" class="headerlink" title="1.5.6 通过请求方式匹配"></a><strong>1.5.6</strong> 通过请求方式匹配</h3><p>可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line"></span><br><span class="line">        <span class="string">-id:</span> <span class="string">gateway-service</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line"></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Method=GET</span></span><br></pre></td></tr></table></figure>

<p>使用 curl 测试，命令行输入:</p>
<p># curl 默认是以 GET 的方式去请求</p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080</a></p>
<p>测试返回页面代码，证明匹配到路由，我们再以 POST 的方式请求测试。</p>
<p># curl 默认是以 GET 的方式去请求</p>
<p>curl -X POST <a target="_blank" rel="noopener" href="http://localhost:8080/">http://localhost:8080</a></p>
<p>返回 404 没有找到，证明没有匹配上路由</p>
<h3 id="1-5-7-通过请求路径匹配"><a href="#1-5-7-通过请求路径匹配" class="headerlink" title="1.5.7 通过请求路径匹配"></a><strong>1.5.7</strong> 通过请求路径匹配</h3><p>Path Route Predicate 接收一个匹配路径的参数来判断是否走路由。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line"></span><br><span class="line">        <span class="string">-id:</span> <span class="string">gateway-service</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">http://ityouknow.com</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line"></span><br><span class="line">            <span class="string">-Path=/foo/&#123;segment&#125;</span></span><br></pre></td></tr></table></figure>

<p>如果请求路径符合要求，则此路由将匹配，例如：/foo/1 或者 /foo/bar。</p>
<p>使用 curl 测试，命令行输入:</p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/foo/1">http://localhost:8080/foo/1</a></p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/foo/xx">http://localhost:8080/foo/xx</a></p>
<p>curl <a target="_blank" rel="noopener" href="http://localhost:8080/boo/xx">http://localhost:8080/boo/xx</a></p>
<p>经过测试第一和第二条命令可以正常获取到页面返回值，最后一个命令报404，证明路由是通过指定路由来匹配。</p>
<h3 id="1-5-8-通过请求-ip-地址进行匹配"><a href="#1-5-8-通过请求-ip-地址进行匹配" class="headerlink" title="1.5.8 通过请求 ip 地址进行匹配"></a><strong>1.5.8</strong> 通过请求 ip 地址进行匹配</h3><p>Predicate 也支持通过设置某个 ip 区间号段的请求才会路由，RemoteAddr Route Predicate 接受 cidr 符号(IPv4 或 IPv6 )字符串的列表(最小大小为1)，例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址，16 是子网掩码)。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line"></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line"></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">gateway-service</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line"></span><br><span class="line">            <span class="bullet">-</span> <span class="string">RemoteAddr=192.168.1.1/24</span></span><br></pre></td></tr></table></figure>

<p>可以将此地址设置为本机的 ip 地址进行测试。</p>
<p>curl localhost:8080</p>
<p>如果请求的远程地址是 192.168.1.10，则此路由将匹配。</p>
<h3 id="1-5-10-组合使用"><a href="#1-5-10-组合使用" class="headerlink" title="1.5.10 组合使用"></a><strong>1.5.10</strong> <strong>组合使用</strong></h3><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">api-gateway</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">gateway-service</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">https://www.baidu.com</span></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Host=**.foo.org</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Path=/headers</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Method=GET</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Header=X-Request-Id,</span> <span class="string">\d+</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Query=foo,</span> <span class="string">ba.</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Query=baz</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Cookie=chocolate,</span> <span class="string">ch.p</span></span><br></pre></td></tr></table></figure>

<p>各种 Predicates 同时存在于同一个路由时，请求必须同时满足所有的条件才被这个路由匹配。</p>
<p>一个请求满足多个路由的断言条件时，请求只会被首个成功匹配的路由转发</p>
<h2 id="3-2-过滤器规则（Filter）"><a href="#3-2-过滤器规则（Filter）" class="headerlink" title="3.2 过滤器规则（Filter）"></a>3.2 过滤器规则（Filter）</h2><h3 id="过滤器规则（Filter）"><a href="#过滤器规则（Filter）" class="headerlink" title="过滤器规则（Filter）"></a>过滤器规则（Filter）</h3><table>
<thead>
<tr>
<th align="left">过滤规则</th>
<th align="left">实例</th>
<th align="left">说明</th>
</tr>
</thead>
<tbody><tr>
<td align="left">PrefixPath</td>
<td align="left">- PrefixPath=/app</td>
<td align="left">在请求路径前加上app</td>
</tr>
<tr>
<td align="left">RewritePath</td>
<td align="left">- RewritePath=/test, /app/test</td>
<td align="left">访问localhost:9022/test,请求会转发到localhost:8001/app/test</td>
</tr>
<tr>
<td align="left">SetPath</td>
<td align="left">SetPath=/app/{path}</td>
<td align="left">通过模板设置路径，转发的规则时会在路径前增加app，{path}表示原请求路径</td>
</tr>
<tr>
<td align="left">RedirectTo</td>
<td align="left"></td>
<td align="left">重定向</td>
</tr>
<tr>
<td align="left">RemoveRequestHeader</td>
<td align="left"></td>
<td align="left">去掉某个请求头信息</td>
</tr>
</tbody></table>
<p>注：当配置多个filter时，优先定义的会被调用，剩余的filter将不会生效</p>
<h3 id="PrefixPath"><a href="#PrefixPath" class="headerlink" title="PrefixPath"></a>PrefixPath</h3><p>对所有的请求路径添加前缀：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">prefixpath_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">PrefixPath=/mypath</span></span><br></pre></td></tr></table></figure>

<p>访问/hello的请求被发送到<a target="_blank" rel="noopener" href="https://example.org/mypath/hello%E3%80%82">https://example.org/mypath/hello。</a></p>
<h3 id="RedirectTo"><a href="#RedirectTo" class="headerlink" title="RedirectTo"></a>RedirectTo</h3><p>重定向，配置包含重定向的返回码和地址：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">prefixpath_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">RedirectTo=302,</span> <span class="string">https://acme.org</span></span><br></pre></td></tr></table></figure>

<h3 id="RemoveRequestHeader"><a href="#RemoveRequestHeader" class="headerlink" title="RemoveRequestHeader"></a>RemoveRequestHeader</h3><p>去掉某个请求头信息：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">removerequestheader_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">RemoveRequestHeader=X-Request-Foo</span></span><br></pre></td></tr></table></figure>

<p>去掉请求头信息 X-Request-Foo</p>
<h3 id="RemoveResponseHeader"><a href="#RemoveResponseHeader" class="headerlink" title="RemoveResponseHeader"></a>RemoveResponseHeader</h3><p>去掉某个回执头信息：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">removerequestheader_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">RemoveResponseHeader=X-Request-Foo</span></span><br></pre></td></tr></table></figure>

<h3 id="RemoveRequestParameter"><a href="#RemoveRequestParameter" class="headerlink" title="RemoveRequestParameter"></a>RemoveRequestParameter</h3><p>去掉某个请求参数信息：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">removerequestparameter_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">RemoveRequestParameter=red</span></span><br></pre></td></tr></table></figure>

<h3 id="RewritePath"><a href="#RewritePath" class="headerlink" title="RewritePath"></a>RewritePath</h3><p>改写路径：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">rewrite_filter</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">http://localhost:8081</span></span><br><span class="line">        <span class="attr">predicates:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Path=/test/**</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">RewritePath=/where(?&lt;segment&gt;/?.*),</span> <span class="string">/test(?&lt;segment&gt;/?.*)</span></span><br></pre></td></tr></table></figure>

<p>/where/… 改成 test/…</p>
<p>使用代码改下路径</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">RouteLocatorBuilder.Builder builder = routeLocatorBuilder.routes();</span><br><span class="line">   builder</span><br><span class="line">           .route(<span class="string">&quot;path_rote_at_guigu&quot;</span>, r -&gt; r.path(<span class="string">&quot;/guonei&quot;</span>)</span><br><span class="line">                   .uri(<span class="string">&quot;http://news.baidu.com/guonei&quot;</span>))</span><br><span class="line">           .route(<span class="string">&quot;csdn_route&quot;</span>, r -&gt; r.path(<span class="string">&quot;/csdn&quot;</span>)</span><br><span class="line">                   .uri(<span class="string">&quot;https://blog.csdn.net&quot;</span>))</span><br><span class="line">           .route(<span class="string">&quot;blog3_rewrite_filter&quot;</span>, r -&gt; r.path(<span class="string">&quot;/blog3/**&quot;</span>)</span><br><span class="line">                   .filters(f -&gt; f.rewritePath(<span class="string">&quot;/blog3/(?&lt;segment&gt;.*)&quot;</span>, <span class="string">&quot;/$\\&#123;segment&#125;&quot;</span>))</span><br><span class="line">                   .uri(<span class="string">&quot;https://blog.csdn.net&quot;</span>))</span><br><span class="line">           .route(<span class="string">&quot;rewritepath_route&quot;</span>, r -&gt; r.path(<span class="string">&quot;/baidu/**&quot;</span>)</span><br><span class="line">                   .filters(f -&gt; f.rewritePath(<span class="string">&quot;/baidu/(?&lt;segment&gt;.*)&quot;</span>, <span class="string">&quot;/$\\&#123;segment&#125;&quot;</span>))</span><br><span class="line">                   .uri(<span class="string">&quot;http://www.baidu.com&quot;</span>))</span><br><span class="line"></span><br><span class="line">           .build();</span><br></pre></td></tr></table></figure>

<h3 id="SetPath"><a href="#SetPath" class="headerlink" title="SetPath"></a>SetPath</h3><p>设置请求路径，与RewritePath类似。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">setpath_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">predicates:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Path=/red/&#123;segment&#125;</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">SetPath=/&#123;segment&#125;</span></span><br></pre></td></tr></table></figure>

<p>如/red/blue的请求被转发到/blue。</p>
<h3 id="SetRequestHeader"><a href="#SetRequestHeader" class="headerlink" title="SetRequestHeader"></a>SetRequestHeader</h3><p>设置请求头信息。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">setrequestheader_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">SetRequestHeader=X-Request-Red,</span> <span class="string">Blue</span></span><br></pre></td></tr></table></figure>

<h3 id="SetStatus"><a href="#SetStatus" class="headerlink" title="SetStatus"></a>SetStatus</h3><p>设置回执状态码。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">setstatusint_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://example.org</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">SetStatus=401</span></span><br></pre></td></tr></table></figure>

<h3 id="StripPrefix"><a href="#StripPrefix" class="headerlink" title="StripPrefix"></a>StripPrefix</h3><p>跳过指定路径。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">nameRoot</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">https://nameservice</span></span><br><span class="line">        <span class="attr">predicates:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Path=/name/**</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">StripPrefix=2</span></span><br></pre></td></tr></table></figure>

<p>请求/name/blue/red会转发到/red。</p>
<h3 id="RequestSize"><a href="#RequestSize" class="headerlink" title="RequestSize"></a>RequestSize</h3><p>请求大小。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">request_size_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">http://localhost:8080/upload</span></span><br><span class="line">        <span class="attr">predicates:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Path=/upload</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">RequestSize</span></span><br><span class="line">          <span class="attr">args:</span></span><br><span class="line">            <span class="attr">maxSize:</span> <span class="number">5000000</span></span><br></pre></td></tr></table></figure>

<p>超过5M的请求会返回413错误。</p>
<h3 id="Default-filters"><a href="#Default-filters" class="headerlink" title="Default-filters"></a>Default-filters</h3><p>对所有请求添加过滤器。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">default-filters:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">AddResponseHeader=X-Response-Default-Red,</span> <span class="string">Default-Blue</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">PrefixPath=/httpbin</span></span><br></pre></td></tr></table></figure>

<h2 id="3-3-通过代码进行配置"><a href="#3-3-通过代码进行配置" class="headerlink" title="3.3 通过代码进行配置"></a>3.3 通过代码进行配置</h2><p>通过代码进行配置，将路由规则设置为一个Bean即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> RouteLocator <span class="title">customRouteLocator</span><span class="params">(RouteLocatorBuilder builder)</span> </span>&#123;</span><br><span class="line">	<span class="keyword">return</span> builder.routes()</span><br><span class="line">		.route(<span class="string">&quot;path_route&quot;</span>, r -&gt; r.path(<span class="string">&quot;/get&quot;</span>)</span><br><span class="line">			.uri(<span class="string">&quot;http://httpbin.org&quot;</span>))</span><br><span class="line">		.route(<span class="string">&quot;host_route&quot;</span>, r -&gt; r.host(<span class="string">&quot;*.myhost.org&quot;</span>)</span><br><span class="line">			.uri(<span class="string">&quot;http://httpbin.org&quot;</span>))</span><br><span class="line">		.route(<span class="string">&quot;rewrite_route&quot;</span>, r -&gt; r.host(<span class="string">&quot;*.rewrite.org&quot;</span>)</span><br><span class="line">			.filters(f -&gt; f.rewritePath(<span class="string">&quot;/foo/(?&lt;segment&gt;.*)&quot;</span>, <span class="string">&quot;/$&#123;segment&#125;&quot;</span>))</span><br><span class="line">			.uri(<span class="string">&quot;http://httpbin.org&quot;</span>))</span><br><span class="line">		.route(<span class="string">&quot;hystrix_route&quot;</span>, r -&gt; r.host(<span class="string">&quot;*.hystrix.org&quot;</span>)</span><br><span class="line">			.filters(f -&gt; f.hystrix(c -&gt; c.setName(<span class="string">&quot;slowcmd&quot;</span>)))</span><br><span class="line">			.uri(<span class="string">&quot;http://httpbin.org&quot;</span>))</span><br><span class="line">		.route(<span class="string">&quot;hystrix_fallback_route&quot;</span>, r -&gt; r.host(<span class="string">&quot;*.hystrixfallback.org&quot;</span>)</span><br><span class="line">			.filters(f -&gt; f.hystrix(c -&gt; c.setName(<span class="string">&quot;slowcmd&quot;</span>).setFallbackUri(<span class="string">&quot;forward:/hystrixfallback&quot;</span>)))</span><br><span class="line">			.uri(<span class="string">&quot;http://httpbin.org&quot;</span>))</span><br><span class="line">		.route(<span class="string">&quot;limit_route&quot;</span>, r -&gt; r</span><br><span class="line">			.host(<span class="string">&quot;*.limited.org&quot;</span>).and().path(<span class="string">&quot;/anything/**&quot;</span>)</span><br><span class="line">			.filters(f -&gt; f.requestRateLimiter(c -&gt; c.setRateLimiter(redisRateLimiter())))</span><br><span class="line">			.uri(<span class="string">&quot;http://httpbin.org&quot;</span>))</span><br><span class="line">		.build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3-2-实现熔断降级"><a href="#3-2-实现熔断降级" class="headerlink" title="3.2 实现熔断降级"></a><strong>3.2</strong> 实现熔断降级</h2><p>为什么要实现熔断降级？</p>
<p>在分布式系统中，网关作为流量的入口，因此会有大量的请求进入网关，向其他服务发起调用，其他服务不可避免的会出现调用失败（超时、异常），失败时不能让请求堆积在网关上，需要快速失败并返回给客户端，想要实现这个要求，就必须在网关上做熔断、降级操作。</p>
<p>为什么在网关上请求失败需要快速返回给客户端？</p>
<p>因为当一个客户端请求发生故障的时候，这个请求会一直堆积在网关上，当然只有一个这种请求，网关肯定没有问题（如果一个请求就能造成整个系统瘫痪，那这个系统可以下架了），但是网关上堆积多了就会给网关乃至整个服务都造成巨大的压力，甚至整个服务宕掉。因此要对一些服务和页面进行有策略的降级，以此缓解服务器资源的的压力，以保证核心业务的正常运行，同时也保持了客户和大部分客户的得到正确的相应，所以需要网关上请求失败需要快速返回给客户端。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server.port:</span> <span class="number">8082</span></span><br><span class="line"></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">gateway</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">      <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">      <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">      <span class="attr">password:</span> <span class="number">123456</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">rateLimit_route</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">http://localhost:8000</span></span><br><span class="line">          <span class="attr">order:</span> <span class="number">0</span></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Path=/test/**</span></span><br><span class="line">          <span class="attr">filters:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">StripPrefix=1</span></span><br><span class="line">            <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Hystrix</span></span><br><span class="line">              <span class="attr">args:</span></span><br><span class="line">                <span class="attr">name:</span> <span class="string">fallbackCmdA</span></span><br><span class="line">                <span class="attr">fallbackUri:</span> <span class="string">forward:/fallbackA</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">hystrix.command.fallbackCmdA.execution.isolation.thread.timeoutInMilliseconds:</span> <span class="number">5000</span></span><br></pre></td></tr></table></figure>

<p>这里的配置，使用了两个过滤器：</p>
<p>（1）过滤器StripPrefix，作用是去掉请求路径的最前面n个部分截取掉。</p>
<p>StripPrefix=1就代表截取路径的个数为1，比如前端过来请求/test/good/1/view，匹配成功后，路由到后端的请求路径就会变成<a target="_blank" rel="noopener" href="http://localhost:8888/good/1/view%E3%80%82">http://localhost:8888/good/1/view。</a></p>
<p>（2）过滤器Hystrix，作用是通过Hystrix进行熔断降级</p>
<p>当上游的请求，进入了Hystrix熔断降级机制时，就会调用fallbackUri配置的降级地址。需要注意的是，还需要单独设置Hystrix的commandKey的超时时间</p>
<p>fallbackUri配置的降级地址的代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> org.gateway.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.gateway.response.Response;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.GetMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FallbackController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/fallbackA&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Response <span class="title">fallbackA</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Response response = <span class="keyword">new</span> Response();</span><br><span class="line">        response.setCode(<span class="string">&quot;100&quot;</span>);</span><br><span class="line">        response.setMessage(<span class="string">&quot;服务暂时不可用&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> response;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="4-高级配置"><a href="#4-高级配置" class="headerlink" title="4 高级配置"></a>4 高级配置</h1><h2 id="4-1-分布式限流"><a href="#4-1-分布式限流" class="headerlink" title="4.1 分布式限流"></a>4.1 分布式限流</h2><p>从某种意义上讲，令牌桶算法是对漏桶算法的一种改进，桶算法能够限制请求调用的速率，而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中，存在一个桶，用来存放固定数量的令牌。算法中存在一种机制，以一定的速率往桶中放令牌。每次请求调用需要先获取令牌，只有拿到令牌，才有机会继续执行，否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行，如果桶中令牌数达到上限，就丢弃令牌，所以就存在这种情况，桶中一直有大量的可用令牌，这时进来的请求就可以直接拿到令牌执行，比如设置qps为100，那么限流器初始化完成一秒后，桶中就已经有100个令牌了，这时服务还没完全启动好，等启动完成对外提供服务时，该限流器可以抵挡瞬时的100个请求。所以，只有桶中没有令牌时，请求才会进行等待，最后相当于以一定的速率执行。<br><a target="_blank" rel="noopener" href="https://upload-images.jianshu.io/upload_images/19816137-89297e59a487540d?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><img src="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947763.jpeg" alt="在这里插入图片描述"></a></p>
<p>在Spring Cloud Gateway中，有Filter过滤器，因此可以在“pre”类型的Filter中自行实现上述三种过滤器。但是限流作为网关最基本的功能，Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory这个类，适用在Redis内的通过执行Lua脚本实现了令牌桶的方式。具体实现逻辑在RequestRateLimiterGatewayFilterFactory类中，lua脚本在如下图所示的文件夹中：<br><a target="_blank" rel="noopener" href="https://upload-images.jianshu.io/upload_images/19816137-0456652619daecaa?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><img src="https://gitee.com/littlefxc/oss/raw/master/images/1240-20210407151947778.jpeg" alt="在这里插入图片描述"></a></p>
<p>首先在工程的pom文件中引入gateway的起步依赖和redis的reactive依赖，代码如下：</p>
<p>配置如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8081</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">limit_route</span></span><br><span class="line">        <span class="attr">uri:</span> <span class="string">http://httpbin.org:80/get</span></span><br><span class="line">        <span class="attr">predicates:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">After=2017-01-20T17:42:47.789-07:00[America/Denver]</span></span><br><span class="line">        <span class="attr">filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">RequestRateLimiter</span></span><br><span class="line">          <span class="attr">args:</span></span><br><span class="line">            <span class="attr">key-resolver:</span> <span class="string">&#x27;#&#123;@userKeyResolver&#125;&#x27;</span></span><br><span class="line">            <span class="attr">redis-rate-limiter.replenishRate:</span> <span class="number">1</span></span><br><span class="line">            <span class="attr">redis-rate-limiter.burstCapacity:</span> <span class="number">3</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">cloud-gateway</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">localhost</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">    <span class="attr">database:</span> <span class="number">0</span></span><br></pre></td></tr></table></figure>

<p>​    在上面的配置文件，指定程序的端口为8081，配置了 redis的信息，并配置了RequestRateLimiter的限流过滤器，该过滤器需要配置三个参数：</p>
<ul>
<li>burstCapacity，令牌桶总容量。</li>
<li>replenishRate，令牌桶每秒填充平均速率。</li>
<li>key-resolver，用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象。</li>
</ul>
<p>这里根据用户ID限流，请求路径中必须携带userId参数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function">KeyResolver <span class="title">userKeyResolver</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> exchange -&gt; Mono.just(exchange.getRequest().getQueryParams().getFirst(<span class="string">&quot;user&quot;</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>KeyResolver需要实现resolve方法，比如根据userid进行限流，则需要用userid去判断。实现完KeyResolver之后，需要将这个类的Bean注册到Ioc容器中。</p>
<p>如果需要根据IP限流，定义的获取限流Key的bean为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> KeyResolver <span class="title">ipKeyResolver</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> exchange -&gt; Mono.just(exchange.getRequest().getRemoteAddress().getHostName());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通过exchange对象可以获取到请求信息，这边用了HostName，如果你想根据用户来做限流的话这边可以获取当前请求的用户ID或者用户名就可以了，比如：</p>
<p>如果需要根据接口的URI进行限流，则需要获取请求地址的uri作为限流key，定义的Bean对象为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> </span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function">KeyResolver <span class="title">apiKeyResolver</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> exchange -&gt; Mono.just(exchange.getRequest().getPath().value());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="4-2-健康检查配置"><a href="#4-2-健康检查配置" class="headerlink" title="4.2 健康检查配置"></a>4.2 健康检查配置</h2><p>admin-client、actuator健康检查配置，为之后的功能提供支持，此部分比较简单，不再赘述，加入以下maven依赖和配置</p>
<h4 id="maven依赖"><a href="#maven依赖" class="headerlink" title="maven依赖"></a>maven依赖</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-actuator<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>de.codecentric<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-admin-starter-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-netflix-eureka-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h4 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h4><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">mas-cloud-gateway</span></span><br><span class="line">  <span class="attr">boot:</span></span><br><span class="line">    <span class="attr">admin:</span></span><br><span class="line">      <span class="attr">client:</span></span><br><span class="line">      <span class="comment">### 本地搭建的admin-server</span></span><br><span class="line">        <span class="attr">url:</span> <span class="string">http://localhost:8011</span></span><br><span class="line"><span class="attr">eureka:</span></span><br><span class="line">  <span class="attr">client:</span></span><br><span class="line">    <span class="attr">registerWithEureka:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">fetchRegistry:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">serviceUrl:</span></span><br><span class="line">      <span class="attr">defaultZone:</span> <span class="string">http://localhost:6887/eureka/</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">feign:</span></span><br><span class="line">  <span class="attr">sentinel:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">management:</span></span><br><span class="line">  <span class="attr">endpoints:</span></span><br><span class="line">    <span class="attr">web:</span></span><br><span class="line">      <span class="attr">exposure:</span></span><br><span class="line">        <span class="attr">include:</span> <span class="string">&#x27;*&#x27;</span></span><br><span class="line">  <span class="attr">endpoint:</span></span><br><span class="line">    <span class="attr">health:</span></span><br><span class="line">      <span class="attr">show-details:</span> <span class="string">ALWAYS</span></span><br></pre></td></tr></table></figure>

<p>若转发的目标地址为微服务中组件，不为具体ip:port形式的，应写成lb://mas-openapi-service形式，目标地址会从注册中心直接拉取</p>
<h2 id="4-3-统一配置跨域请求："><a href="#4-3-统一配置跨域请求：" class="headerlink" title="4.3 统一配置跨域请求："></a>4.3 统一配置跨域请求：</h2><p>现在的请求通过经过gateWay网关时，需要在网关统一配置跨域请求，需求所有请求通过</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">globalcors:</span></span><br><span class="line">        <span class="attr">cors-configurations:</span></span><br><span class="line">          <span class="string">&#x27;[/**]&#x27;</span><span class="string">:</span></span><br><span class="line">            <span class="attr">allowed-origins:</span> <span class="string">&quot;*&quot;</span></span><br><span class="line">            <span class="attr">allowed-headers:</span> <span class="string">&quot;*&quot;</span></span><br><span class="line">            <span class="attr">allow-credentials:</span> <span class="literal">true</span></span><br><span class="line">            <span class="attr">allowed-methods:</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">GET</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">POST</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">DELETE</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">PUT</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">OPTION</span></span><br></pre></td></tr></table></figure>

<h1 id="5-整合Nacos"><a href="#5-整合Nacos" class="headerlink" title="5 整合Nacos"></a>5 整合Nacos</h1><h2 id="maven依赖-1"><a href="#maven依赖-1" class="headerlink" title="maven依赖"></a>maven依赖</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.9.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">relativePath</span>/&gt;</span> <span class="comment">&lt;!-- lookup parent from repository --&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.example<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>nacos_gateway<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.0.1-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">packaging</span>&gt;</span>war<span class="tag">&lt;/<span class="name">packaging</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">name</span>&gt;</span>nacos_gateway<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">description</span>&gt;</span>Demo project for Spring Boot<span class="tag">&lt;/<span class="name">description</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">java.version</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">java.version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">spring-cloud.version</span>&gt;</span>Greenwich.SR3<span class="tag">&lt;/<span class="name">spring-cloud.version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--gateway--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-gateway<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--nacos dicovery--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring-cloud.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">type</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">type</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">scope</span>&gt;</span>import<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-alibaba-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.2.2.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">type</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">type</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">scope</span>&gt;</span>import<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>需要注意在Gateway服务中的pom.xml文件中不要存在这个jar</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-tomcat<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>provided<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>否则调用接口时会报以下错误因为gateway使用的是webflux,默认使用netty,所以从依赖中排除 tomcat相关的依赖</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">java.lang.ClassCastException: org.springframework.core.io.buffer.DefaultDataBufferFactory cannot be cast to org.springframework.core.io.buffer.NettyDataBufferFactory</span><br><span class="line">	at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.lambda$filter$1(NettyWriteResponseFilter.java:82) ~[spring-cloud-gateway-core-2.1.3.RELEASE.jar:2.1.3.RELEASE]</span><br><span class="line">	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44) [reactor-core-3.2.12.RELEASE.jar:3.2.12.RELEASE]</span><br></pre></td></tr></table></figure>

<p>错误2 是由于 spring-boot-starter-web 引起</p>
<h2 id="服务发现配置：从Nacos获取微服务提供者清单"><a href="#服务发现配置：从Nacos获取微服务提供者清单" class="headerlink" title="服务发现配置：从Nacos获取微服务提供者清单"></a>服务发现配置：从Nacos获取微服务提供者清单</h2><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8087</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">nacos_gateway</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">nacos:</span></span><br><span class="line">      <span class="attr">discovery:</span></span><br><span class="line">        <span class="attr">server-addr:</span> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span><span class="string">:8848</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">discovery:</span></span><br><span class="line">        <span class="attr">locator:</span></span><br><span class="line">          <span class="attr">enabled:</span> <span class="literal">true</span>  <span class="comment">#表明gateway开启服务注册和发现的功能，并且spring cloud gateway自动根据服务发现为每一个服务创建了一个router，这个router将以服务名开头的请求路径转发到对应的服务</span></span><br><span class="line">          <span class="attr">lower-case-service-id:</span> <span class="literal">true</span>  <span class="comment">#是将请求路径上的服务名配置为小写（因为服务注册的时候，向注册中心注册时将服务名转成大写的了</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">          <span class="string">-id:</span> <span class="string">apiuser</span></span><br><span class="line">          <span class="comment">#</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">lb://nacos-consumer-user</span></span><br><span class="line">          <span class="attr">predicates:</span></span><br><span class="line">          <span class="comment"># http://localhost:6601/user/user/users/2, 必须加上StripPrefix=1，否则访问服务时会带上user</span></span><br><span class="line">          <span class="bullet">-</span> <span class="string">Path=/user/**</span> <span class="comment"># 转发该路径</span></span><br><span class="line">           <span class="comment">#以下是配置例子</span></span><br><span class="line">            <span class="comment"># - id: 163                     #网关路由到网易官网</span></span><br><span class="line">            <span class="comment">#  uri: http://www.163.com/</span></span><br><span class="line">            <span class="comment">#  predicates:</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">Path=/163/**</span></span><br><span class="line">        <span class="comment">#      - id: ORDER-SERVICE           #网关路由到订单服务order-service</span></span><br><span class="line">        <span class="comment">#        uri: lb://ORDER-SERVICE</span></span><br><span class="line">        <span class="comment">#        predicates:</span></span><br><span class="line">        <span class="comment">#          - Path=/ORDER-SERVICE/**</span></span><br><span class="line">        <span class="comment">#      - id: USER-SERVICE            #网关路由到用户服务user-service</span></span><br><span class="line">        <span class="comment">#        uri: lb://USER-SERVICE</span></span><br><span class="line">        <span class="comment">#        predicates:</span></span><br><span class="line">        <span class="comment">#          - Pach=/USER-SERVICE/**</span></span><br></pre></td></tr></table></figure>

<h2 id="nacos实现动态配置"><a href="#nacos实现动态配置" class="headerlink" title="nacos实现动态配置"></a>nacos实现动态配置</h2><p>使用nacos实现动态路由，以上两种方式都是实现的静态配置路径，只能应对部分场景，接下来配置nacos实现动态配置以及配置的存储，由于gateWay并没有适配nacos，需要自定义监听器：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">NacosDynamicRouteService</span> <span class="keyword">implements</span> <span class="title">ApplicationEventPublisherAware</span> </span>&#123;</span><br><span class="line">  <span class="keyword">private</span> String dataId = <span class="string">&quot;gateway-router&quot;</span>;</span><br><span class="line">  <span class="keyword">private</span> String group = <span class="string">&quot;DEFAULT_GROUP&quot;</span>;</span><br><span class="line">  <span class="meta">@Value(&quot;$&#123;spring.cloud.nacos.config.server-addr&#125;&quot;)</span></span><br><span class="line">  <span class="keyword">private</span> String serverAddr;</span><br><span class="line">  <span class="meta">@Autowired</span></span><br><span class="line">  <span class="keyword">private</span> RouteDefinitionWriter routeDefinitionWriter;</span><br><span class="line">  <span class="keyword">private</span> ApplicationEventPublisher applicationEventPublisher;</span><br><span class="line">  <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> List&lt;String&gt; ROUTE_LIST = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">  <span class="meta">@PostConstruct</span></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">dynamicRouteByNacosListener</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      ConfigService configService = NacosFactory.createConfigService(serverAddr);</span><br><span class="line">      configService.getConfig(dataId, group, <span class="number">5000</span>);</span><br><span class="line">      configService.addListener(dataId, group, <span class="keyword">new</span> Listener() &#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">receiveConfigInfo</span><span class="params">(String configInfo)</span> </span>&#123;</span><br><span class="line">          clearRoute();</span><br><span class="line">          <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (StringUtil.isNullOrEmpty(configInfo)) &#123;<span class="comment">//配置被删除</span></span><br><span class="line">              <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            List&lt;RouteDefinition&gt; gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);</span><br><span class="line">            <span class="keyword">for</span> (RouteDefinition routeDefinition : gatewayRouteDefinitions) &#123;</span><br><span class="line">              addRoute(routeDefinition);</span><br><span class="line">            &#125;</span><br><span class="line">            publish();</span><br><span class="line">          &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            log.error(<span class="string">&quot;receiveConfigInfo error&quot;</span> + e);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Executor <span class="title">getExecutor</span><span class="params">()</span> </span>&#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (NacosException e) &#123;</span><br><span class="line">        log.error(<span class="string">&quot;dynamicRouteByNacosListener error&quot;</span> + e);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">clearRoute</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (String id : ROUTE_LIST) &#123;</span><br><span class="line">      <span class="keyword">this</span>.routeDefinitionWriter.delete(Mono.just(id)).subscribe();</span><br><span class="line">    &#125;</span><br><span class="line">    ROUTE_LIST.clear();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">addRoute</span><span class="params">(RouteDefinition definition)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      routeDefinitionWriter.save(Mono.just(definition)).subscribe();</span><br><span class="line">      ROUTE_LIST.add(definition.getId());</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> log.error(<span class="string">&quot;addRoute error&quot;</span> + e);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">publish</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.applicationEventPublisher.publishEvent(<span class="keyword">new</span> RefreshRoutesEvent(<span class="keyword">this</span>.routeDefinitionWriter));</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="meta">@Override</span></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setApplicationEventPublisher</span><span class="params">(ApplicationEventPublisher applicationEventPublisher)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.applicationEventPublisher = applicationEventPublisher;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>在nacos中增加一个规则：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">[&#123;</span><br><span class="line">    <span class="attr">&quot;filters&quot;</span>: [],</span><br><span class="line">    <span class="attr">&quot;id&quot;</span>: <span class="string">&quot;baidu_route&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;order&quot;</span>: <span class="number">0</span>,</span><br><span class="line">    <span class="attr">&quot;predicates&quot;</span>: [&#123;</span><br><span class="line">        <span class="attr">&quot;args&quot;</span>: &#123;</span><br><span class="line">            <span class="attr">&quot;pattern&quot;</span>: <span class="string">&quot;/baidu&quot;</span></span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;Path&quot;</span></span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="attr">&quot;uri&quot;</span>: <span class="string">&quot;https://www.baidu.com&quot;</span></span><br><span class="line">&#125;]</span><br></pre></td></tr></table></figure>

<p>访问网关的路由规则，能看到刚刚加入的规则，访问<em><a target="_blank" rel="noopener" href="http://localhost:9022/baidu">http://localhost:9022/baidu</a></em>时请求直接被转发到百度的首页了。</p>
<p><a target="_blank" rel="noopener" href="https://img-blog.csdnimg.cn/20200325164150414.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0ZvdXNlXw==,size_16,color_FFFFFF,t_70#pic_center"><img src="https://gitee.com/littlefxc/oss/raw/master/images/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0ZvdXNlXw==,size_16,color_FFFFFF,t_70-20210407151947799.png" alt="生效的路径"></a></p>
<h1 id="6-整合Swagger聚合微服务系统API文档"><a href="#6-整合Swagger聚合微服务系统API文档" class="headerlink" title="6 整合Swagger聚合微服务系统API文档"></a>6 整合Swagger聚合微服务系统API文档</h1><h2 id="maven依赖-2"><a href="#maven依赖-2" class="headerlink" title="maven依赖"></a>maven依赖</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>cloud-center-alibaba<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.crazymaker.springcloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.crazymaker.springcloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springcloud-gateway-demo<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">name</span>&gt;</span>springcloud-gateway-demo<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">packaging</span>&gt;</span>jar<span class="tag">&lt;/<span class="name">packaging</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--gateway 网关依赖,内置webflux 依赖 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-gateway<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--新增sentinel--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.csp<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>sentinel-spring-cloud-gateway-adapter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.csp<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>sentinel-transport-simple-http<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- nacos服务注册发现依赖--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.google.guava<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>guava<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;mysql.connector.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- nacos配置服务依赖--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-config<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.google.guava<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>guava<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-netflix-hystrix<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-actuator<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.hutool<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>hutool-all<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;hutool.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger2<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;swagger.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger-common<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;swagger.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.github.xiaoymin<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>swagger-bootstrap-ui<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;swagger-ui.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-commons<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">mainClass</span>&gt;</span>com.crazymaker.cloud.nacos.demo.gateway.starter.GatewayProviderApplication<span class="tag">&lt;/<span class="name">mainClass</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">goal</span>&gt;</span>repackage<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-assembly-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.4.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">descriptors</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">descriptor</span>&gt;</span>src/main/assembly/assembly.xml<span class="tag">&lt;/<span class="name">descriptor</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">descriptors</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">id</span>&gt;</span>make-assembly<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">phase</span>&gt;</span>package<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">goal</span>&gt;</span>single<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="comment">&lt;!-- 添加docker-maven插件 --&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.spotify<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>docker-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.1.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">imageName</span>&gt;</span>dockerlocal:5000/$&#123;project.artifactId&#125;:$&#123;project.version&#125;<span class="tag">&lt;/<span class="name">imageName</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">baseImage</span>&gt;</span>dockerlocal:5000/java<span class="tag">&lt;/<span class="name">baseImage</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">entryPoint</span>&gt;</span>[&quot;java&quot;, &quot;-jar&quot;, &quot;/$&#123;project.build.finalName&#125;.jar&quot;]<span class="tag">&lt;/<span class="name">entryPoint</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">dockerDirectory</span>&gt;</span>docker<span class="tag">&lt;/<span class="name">dockerDirectory</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">resource</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">targetPath</span>&gt;</span>/<span class="tag">&lt;/<span class="name">targetPath</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">directory</span>&gt;</span>$&#123;project.build.directory&#125;<span class="tag">&lt;/<span class="name">directory</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">include</span>&gt;</span>$&#123;project.build.finalName&#125;.jar<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">resource</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="配置文件-1"><a href="#配置文件-1" class="headerlink" title="配置文件"></a>配置文件</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.crazymaker.cloud.nacos.demo.gateway.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.AllArgsConstructor;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.config.GatewayProperties;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.route.RouteLocator;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.support.NameUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Primary;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"><span class="keyword">import</span> springfox.documentation.swagger.web.SwaggerResource;</span><br><span class="line"><span class="keyword">import</span> springfox.documentation.swagger.web.SwaggerResourcesProvider;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span> SwaggerProvider</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@PackageName</span> com.ruoyi.gateway.config</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> daiz</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2019/8/16 10:04</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span> 1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Primary</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SwaggerConfig</span> <span class="keyword">implements</span> <span class="title">SwaggerResourcesProvider</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String API_URI = <span class="string">&quot;/v2/api-docs&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> RouteLocator routeLocator;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> GatewayProperties gatewayProperties;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;SwaggerResource&gt; <span class="title">get</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 网关应用名称,不需要在网关的swagger 上展示</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        String appName = <span class="string">&quot;springcloud-gateway&quot;</span>;</span><br><span class="line"></span><br><span class="line">        List&lt;SwaggerResource&gt; resources = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        List&lt;String&gt; routes = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        <span class="comment">// 取出gateway的route</span></span><br><span class="line">        routeLocator.getRoutes().subscribe(route -&gt; routes.add(route.getId()));</span><br><span class="line">        <span class="comment">// 结合配置的route-路径(Path)，和route过滤，只获取有效的route节点</span></span><br><span class="line">        <span class="comment">// 打开下面注释可以自动扫描接入gateway的服务，为了演示，只扫描system</span></span><br><span class="line">        <span class="comment">// gatewayProperties.getRoutes().stream().filter(routeDefinition -&gt;</span></span><br><span class="line">        <span class="comment">// routes.contains(routeDefinition.getId()))</span></span><br><span class="line">        gatewayProperties.getRoutes().stream()</span><br><span class="line">                .filter(route -&gt; route.getUri().getHost() != <span class="keyword">null</span>)</span><br><span class="line">                .filter(route -&gt; !appName.equals(route.getUri().getHost()))</span><br><span class="line">                .forEach(routeDefinition -&gt; routeDefinition.getPredicates().stream()</span><br><span class="line">                        .filter(predicateDefinition -&gt; (<span class="string">&quot;Path&quot;</span>).equalsIgnoreCase(predicateDefinition.getName()))</span><br><span class="line">                        .forEach(predicateDefinition -&gt; resources</span><br><span class="line">                                .add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs()</span><br><span class="line">                                        .get(NameUtils.GENERATED_NAME_PREFIX + <span class="string">&quot;0&quot;</span>).replace(<span class="string">&quot;/**&quot;</span>, API_URI)))));</span><br><span class="line">        <span class="keyword">return</span> resources;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> SwaggerResource <span class="title">swaggerResource</span><span class="params">(String name, String location)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        SwaggerResource swaggerResource = <span class="keyword">new</span> SwaggerResource();</span><br><span class="line">        swaggerResource.setName(name);</span><br><span class="line">        swaggerResource.setLocation(location);</span><br><span class="line">        swaggerResource.setSwaggerVersion(<span class="string">&quot;2.0&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> swaggerResource;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="效果："><a href="#效果：" class="headerlink" title="效果："></a>效果：</h2><p><a target="_blank" rel="noopener" href="https://img-blog.csdnimg.cn/20210112153623924.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NyYXp5bWFrZXJjaXJjbGU=,size_16,color_FFFFFF,t_70"><img src="https://gitee.com/littlefxc/oss/raw/master/images/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NyYXp5bWFrZXJjaXJjbGU=,size_16,color_FFFFFF,t_70-20210407151947874.png" alt="在这里插入图片描述"></a></p>
<h1 id="7-Gatway-网关的过滤器开发"><a href="#7-Gatway-网关的过滤器开发" class="headerlink" title="7 Gatway 网关的过滤器开发"></a>7 Gatway 网关的过滤器开发</h1><h2 id="7-1-过滤器的执行次序"><a href="#7-1-过滤器的执行次序" class="headerlink" title="7.1 过滤器的执行次序"></a>7.1 过滤器的执行次序</h2><p>Spring-Cloud-Gateway 基于过滤器实现，同 zuul 类似，有<strong>pre</strong>和<strong>post</strong>两种方式的 filter,分别处理<strong>前置逻辑</strong>和<strong>后置逻辑</strong>。客户端的请求先经过<strong>pre</strong>类型的 filter，然后将请求转发到具体的业务服务，收到业务服务的响应之后，再经过<strong>post</strong>类型的 filter 处理，最后返回响应到客户端。</p>
<p>过滤器执行流程如下，<strong>order 越大，优先级越低</strong></p>
<p><a target="_blank" rel="noopener" href="https://gitee.com/idea360/oss/raw/master/images/spring-cloud-gateway-fliter-order.png"><img src="https://gitee.com/littlefxc/oss/raw/master/images/spring-cloud-gateway-fliter-order-20210407151948451.png" alt="img"></a></p>
<p>分为全局过滤器和局部过滤器</p>
<ul>
<li><strong>全局过滤器：</strong></li>
</ul>
<blockquote>
<p>对所有路由生效</p>
<p>2、接口用时统计</p>
</blockquote>
<ul>
<li><strong>局部过滤器：</strong></li>
</ul>
<blockquote>
<p>对指定路由生效</p>
</blockquote>
<h2 id="7-2定义全局过滤器"><a href="#7-2定义全局过滤器" class="headerlink" title="7.2定义全局过滤器"></a>7.2定义全局过滤器</h2><p>实现 GlobalFilter 和 Ordered，重写相关方法，加入到spring容器管理即可，无需配置，全局过滤器对所有的路由都有效。</p>
<p>全局过滤器举例：代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.crazymaker.cloud.nacos.demo.gateway.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GatewayFilterChain;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GlobalFilter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.core.Ordered;</span><br><span class="line"><span class="keyword">import</span> org.springframework.core.annotation.Order;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.server.ServerWebExchange;</span><br><span class="line"><span class="keyword">import</span> reactor.core.publisher.Mono;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FilterConfig</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@Order(-1)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> GlobalFilter <span class="title">a</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> AFilter();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@Order(0)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> GlobalFilter <span class="title">b</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> BFilter();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@Order(1)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> GlobalFilter <span class="title">c</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> CFilter();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Slf4j</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AFilter</span> <span class="keyword">implements</span> <span class="title">GlobalFilter</span>, <span class="title">Ordered</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Mono&lt;Void&gt; <span class="title">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            log.info(<span class="string">&quot;AFilter前置逻辑&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> chain.filter(exchange).then(Mono.fromRunnable(() -&gt;</span><br><span class="line">            &#123;</span><br><span class="line">                log.info(<span class="string">&quot;AFilter后置逻辑&quot;</span>);</span><br><span class="line">            &#125;));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//   值越小，优先级越高</span></span><br><span class="line"><span class="comment">//    int HIGHEST_PRECEDENCE = -2147483648;</span></span><br><span class="line"><span class="comment">//    int LOWEST_PRECEDENCE = 2147483647;</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getOrder</span><span class="params">()</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> HIGHEST_PRECEDENCE + <span class="number">100</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Slf4j</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BFilter</span> <span class="keyword">implements</span> <span class="title">GlobalFilter</span>, <span class="title">Ordered</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Mono&lt;Void&gt; <span class="title">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            log.info(<span class="string">&quot;BFilter前置逻辑&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> chain.filter(exchange).then(Mono.fromRunnable(() -&gt;</span><br><span class="line">            &#123;</span><br><span class="line">                log.info(<span class="string">&quot;BFilter后置逻辑&quot;</span>);</span><br><span class="line">            &#125;));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">//   值越小，优先级越高</span></span><br><span class="line"><span class="comment">//    int HIGHEST_PRECEDENCE = -2147483648;</span></span><br><span class="line"><span class="comment">//    int LOWEST_PRECEDENCE = 2147483647;</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getOrder</span><span class="params">()</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> HIGHEST_PRECEDENCE + <span class="number">200</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Slf4j</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CFilter</span> <span class="keyword">implements</span> <span class="title">GlobalFilter</span>, <span class="title">Ordered</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Mono&lt;Void&gt; <span class="title">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            log.info(<span class="string">&quot;CFilter前置逻辑&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> chain.filter(exchange).then(Mono.fromRunnable(() -&gt;</span><br><span class="line">            &#123;</span><br><span class="line">                log.info(<span class="string">&quot;CFilter后置逻辑&quot;</span>);</span><br><span class="line">            &#125;));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//   值越小，优先级越高</span></span><br><span class="line"><span class="comment">//    int HIGHEST_PRECEDENCE = -2147483648;</span></span><br><span class="line"><span class="comment">//    int LOWEST_PRECEDENCE = 2147483647;</span></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getOrder</span><span class="params">()</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> HIGHEST_PRECEDENCE + <span class="number">300</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="7-3定义局部过滤器"><a href="#7-3定义局部过滤器" class="headerlink" title="7.3定义局部过滤器"></a>7.3定义局部过滤器</h2><p>步骤：</p>
<ol>
<li><p>需要实现GatewayFilter, Ordered，实现相关的方法</p>
</li>
<li><p>加入到过滤器工厂，并且注册到spring容器中。</p>
</li>
<li><p>在配置文件中进行配置，如果不配置则不启用此过滤器规则。</p>
</li>
</ol>
<p>局部过滤器举例, 对请求头部的 user-id 进行校验，代码如下：</p>
<ol>
<li><p>需要实现GatewayFilter, Ordered，实现相关的方法</p>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.crazymaker.cloud.nacos.demo.gateway.filter;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang3.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GatewayFilter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GatewayFilterChain;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GlobalFilter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.core.Ordered;</span><br><span class="line"><span class="keyword">import</span> org.springframework.http.HttpStatus;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.server.ServerWebExchange;</span><br><span class="line"><span class="keyword">import</span> reactor.core.publisher.Mono;</span><br><span class="line"></span><br><span class="line"><span class="comment">//@Component</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserIdCheckGateWayFilter</span> <span class="keyword">implements</span> <span class="title">GatewayFilter</span>, <span class="title">Ordered</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Mono&lt;Void&gt; <span class="title">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        String url = exchange.getRequest().getPath().pathWithinApplication().value();</span><br><span class="line">        log.info(<span class="string">&quot;请求URL:&quot;</span> + url);</span><br><span class="line">        log.info(<span class="string">&quot;method:&quot;</span> + exchange.getRequest().getMethod());</span><br><span class="line">       <span class="comment">/*   String secret = exchange.getRequest().getHeaders().getFirst(&quot;secret&quot;);</span></span><br><span class="line"><span class="comment">        if (StringUtils.isBlank(secret))</span></span><br><span class="line"><span class="comment">        &#123;</span></span><br><span class="line"><span class="comment">            return chain.filter(exchange);</span></span><br><span class="line"><span class="comment">        &#125;*/</span></span><br><span class="line">         <span class="comment">//获取param 请求参数</span></span><br><span class="line">        String uname = exchange.getRequest().getQueryParams().getFirst(<span class="string">&quot;uname&quot;</span>);</span><br><span class="line">        <span class="comment">//获取header</span></span><br><span class="line">        String userId = exchange.getRequest().getHeaders().getFirst(<span class="string">&quot;user-id&quot;</span>);</span><br><span class="line">        log.info(<span class="string">&quot;userId：&quot;</span> + userId);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (StringUtils.isBlank(userId))</span><br><span class="line">        &#123;</span><br><span class="line">            log.info(<span class="string">&quot;*****头部验证不通过，请在头部输入  user-id&quot;</span>);</span><br><span class="line">            <span class="comment">//终止请求，直接回应</span></span><br><span class="line">            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);</span><br><span class="line">            <span class="keyword">return</span> exchange.getResponse().setComplete();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> chain.filter(exchange);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//   值越小，优先级越高</span></span><br><span class="line"><span class="comment">//    int HIGHEST_PRECEDENCE = -2147483648;</span></span><br><span class="line"><span class="comment">//    int LOWEST_PRECEDENCE = 2147483647;</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getOrder</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> HIGHEST_PRECEDENCE;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>加入到过滤器工厂，并且注册到spring容器中。</p>
 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.crazymaker.cloud.nacos.demo.gateway.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.crazymaker.cloud.nacos.demo.gateway.filter.UserIdCheckGateWayFilter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.GatewayFilter;</span><br><span class="line"><span class="keyword">import</span> org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserIdCheckGatewayFilterFactory</span> <span class="keyword">extends</span> <span class="title">AbstractGatewayFilterFactory</span>&lt;<span class="title">Object</span>&gt;</span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> GatewayFilter <span class="title">apply</span><span class="params">(Object config)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> UserIdCheckGateWayFilter();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>在配置文件中进行配置，如果不配置则不启用此过滤器规则。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">id:</span> <span class="string">service_provider_demo_route_filter</span></span><br><span class="line">  <span class="attr">uri:</span> <span class="string">lb://service-provider-demo</span></span><br><span class="line">  <span class="attr">predicates:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">Path=/filter/**</span></span><br><span class="line">  <span class="attr">filters:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">RewritePath=/filter/(?&lt;segment&gt;.*),</span> <span class="string">/provider/$\&#123;segment&#125;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">UserIdCheck</span></span><br></pre></td></tr></table></figure></li>
</ol>
<h1 id="8-整合Sentinel完成流控和降级"><a href="#8-整合Sentinel完成流控和降级" class="headerlink" title="8 整合Sentinel完成流控和降级"></a>8 整合Sentinel完成流控和降级</h1><h2 id="maven依赖-3"><a href="#maven依赖-3" class="headerlink" title="maven依赖"></a>maven依赖</h2><p>使用Sentinel作为gateWay的限流、降级、系统保护工具</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--alibaba 流量卫士--&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.csp<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>sentinel-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;sentinel.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-sentinel<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.csp<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>sentinel-spring-cloud-gateway-adapter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="配置文件-2"><a href="#配置文件-2" class="headerlink" title="配置文件"></a>配置文件</h2><p>客户端配置：在配置文件中增加下列配置，dashboard就可以轻松管理客户端了，还有一种方式是在启动时加入</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">sentinel:</span></span><br><span class="line">      <span class="attr">transport:</span></span><br><span class="line">        <span class="comment">## VM</span></span><br><span class="line">        <span class="comment">##-Djava.net.preferIPv4Stack=true -Dcsp.sentinel.dashboard.server=localhost:8080 -Dcsp.sentinel.api.port=8666 -Dproject.name=gateway -Dcsp.sentinel.app.type=1</span></span><br><span class="line">        <span class="attr">dashboard:</span> <span class="string">localhost:8880</span></span><br><span class="line">        <span class="attr">port:</span> <span class="number">8880</span></span><br></pre></td></tr></table></figure>

<h2 id="限流规则通用配置"><a href="#限流规则通用配置" class="headerlink" title="限流规则通用配置"></a>限流规则通用配置</h2><p>由于sentinel的工作原理其实借助于全局的filter进行请求拦截并计算出是否进行限流、熔断等操作的，增加SentinelGateWayFilter配置</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span><span class="comment">//拦截请求</span></span><br><span class="line"><span class="meta">@Order(Ordered.HIGHEST_PRECEDENCE)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> GlobalFilter <span class="title">sentinelGatewayFilter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> SentinelGatewayFilter();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>sentinel 不仅支持通过硬代码方式进行资源的申明，还能通过注解方式进行声明，为了让注解生效，还需要配置切面类SentinelResourceAspect</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> SentinelResourceAspect <span class="title">sentinelResourceAspect</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> SentinelResourceAspect();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>sentinel拦截包括了视图、静态资源等，需要配置viewResolvers以及拦截之后的异常，我们也可以自定义抛出异常的提示</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">SentinelConfig</span><span class="params">(ObjectProvider&lt;List&lt;ViewResolver&gt;&gt; viewResolversProvider,</span></span></span><br><span class="line"><span class="function"><span class="params">                      ServerCodecConfigurer serverCodecConfigurer)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);</span><br><span class="line">  <span class="keyword">this</span>.serverCodecConfigurer = serverCodecConfigurer;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Bean</span><span class="comment">//自定义异常</span></span><br><span class="line"><span class="meta">@Order(Ordered.HIGHEST_PRECEDENCE)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ExceptionHandler <span class="title">sentinelGatewayBlockExceptionHandler</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="comment">// Register the block exception handler for Spring Cloud Gateway.</span></span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> ExceptionHandler(viewResolvers, serverCodecConfigurer);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>自定义异常提示：当发生限流、熔断异常时，会返回定义的提示信息。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 配置限流的异常处理器:SentinelGatewayBlockExceptionHandler</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="meta">@Order(Ordered.HIGHEST_PRECEDENCE)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> SentinelGatewayBlockExceptionHandler <span class="title">sentinelGatewayBlockExceptionHandler</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> SentinelGatewayBlockExceptionHandlerEX(viewResolvers, serverCodecConfigurer);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>不需要额外的配置，sentinel就已经可以正常工作了</p>
<h2 id="限流规则设置"><a href="#限流规则设置" class="headerlink" title="限流规则设置"></a>限流规则设置</h2><p>1 资源定义：定义API组</p>
<p>2 定义限流规则</p>
<h2 id="网关限流参数"><a href="#网关限流参数" class="headerlink" title="网关限流参数"></a>网关限流参数</h2><p>其中网关限流规则 GatewayFlowRule的字段解释如下：</p>
<ul>
<li><p>resource：资源名称，可以是网关中的 route 名称或者用户自定义的 API 分组名称。</p>
</li>
<li><p>resourceMode：规则是针对 API Gateway 的 route（RESOURCE_MODE_ROUTE_ID）还是用户在 Sentinel 中定义的 API 分组（RESOURCE_MODE_CUSTOM_API_NAME），默认是 route。</p>
</li>
<li><p>grade：限流指标维度，同限流规则的 grade 字段。</p>
</li>
<li><p>count：限流阈值</p>
</li>
<li><p>intervalSec：统计时间窗口，单位是秒，默认是 1 秒。</p>
</li>
<li><p>controlBehavior：流量整形的控制效果，同限流规则的 controlBehavior 字段，目前支持快速失败和匀速排队两种模式，默认是快速失败。</p>
</li>
<li><p>burst：应对突发请求时额外允许的请求数目。</p>
</li>
<li><p>maxQueueingTimeoutMs：匀速排队模式下的最长排队时间，单位是毫秒，仅在匀速排队模式下生效。</p>
</li>
<li><p>paramItem</p>
<p>参数限流配置。若不提供，则代表不针对参数进行限流，该网关规则将会被转换成普通流控规则；否则会转换成热点规则。其中的字段：</p>
<ul>
<li>parseStrategy：从请求中提取参数的策略，目前支持提取来源 IP（PARAM_PARSE_STRATEGY_CLIENT_IP）、Host（PARAM_PARSE_STRATEGY_HOST）、任意 Header（PARAM_PARSE_STRATEGY_HEADER）和任意 URL 参数（PARAM_PARSE_STRATEGY_URL_PARAM）四种模式。</li>
<li>fieldName：若提取策略选择 Header 模式或 URL 参数模式，则需要指定对应的 header 名称或 URL 参数名称。</li>
<li>pattern：参数值的匹配模式，只有匹配该模式的请求属性值会纳入统计和流控；若为空则统计该请求属性的所有值。（1.6.2 版本开始支持）</li>
<li>matchStrategy：参数值的匹配策略，目前支持精确匹配（PARAM_MATCH_STRATEGY_EXACT）、子串匹配（PARAM_MATCH_STRATEGY_CONTAINS）和正则匹配（PARAM_MATCH_STRATEGY_REGEX）。（1.6.2 版本开始支持）</li>
</ul>
</li>
</ul>
<p>用户可以通过 GatewayRuleManager.loadRules(rules) 手动加载网关规则，或通过 GatewayRuleManager.register2Property(property) 注册动态规则源动态推送（推荐方式）。</p>

    </div>

    
    
    

    <footer class="post-footer">

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/blog/2021/04/06/flink-java-quickstart/" rel="prev" title="一个 Flink 简单的入门 quickstart">
                  <i class="fa fa-chevron-left"></i> 一个 Flink 简单的入门 quickstart
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/blog/2021/04/07/Kafka-Cluster-Config/" rel="next" title="安装kafka集群">
                  安装kafka集群 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>







<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      const activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      const commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">一年春又来</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/mist/" class="theme-link" rel="noopener" target="_blank">NexT.Mist</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<script src="/blog/js/utils.js"></script><script src="/blog/js/motion.js"></script><script src="/blog/js/schemes/muse.js"></script><script src="/blog/js/next-boot.js"></script>

  
<script src="/blog/js/local-search.js"></script>






  





</body>
</html>
